<?php
class system_encrypt {
	private $_index = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
	private static $_key = '&H0J^L7B~';
	
	private static $_instance = null;
	/**
	 * @return system_encrypt
	 */
	public static function getInstance() {
		if(self::$_instance === null) {
			self::$_instance = new self();
		}
		return self::$_instance;
	}
	
	public static function alphaId($in) {
		if(preg_match('/^[\d]+$/is', $in)) {
			return self::getInstance()->_alphaID($in, false, false);
		} elseif(is_string($in)) {
			return self::getInstance()->_alphaID($in, true, false);
		} else {
			return $in;
		}
	}
	
	public static function shortUrl($input, $len = 6) {
		$hex = crc32($input);
		$rst = sprintf("%u", $hex);
		return self::getInstance()->_alphaID($rst, false, $len);
	}

	public static function shortMd5($input, $rand = false) {
		$base32 = array (
				'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
				'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
				'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
				'y', 'z', '0', '1', '2', '3', '4', '5'
		);
	
		$hex = md5($input . self::getKey());
		$hexLen = strlen($hex);
		$subHexLen = $hexLen / 8;
		$output = array();
	
		for($i = 0; $i < $subHexLen; $i++) {
			$subHex = substr($hex, $i * 8, 8);
			$int = 0x3FFFFFFF & (1 * ('0x' . $subHex));
			$out = '';
			for($j = 0; $j < 6; $j++) {
				$val = 0x0000001F & $int;
				$out .= $base32[$val];
				$int = $int >> 5;
			}
			$output[] = strtoupper($out);
		}
		$index = $rand ? rand(0, count($output) - 1) : 0;
		return $output[$index];
	}
	
	public static function createIdByTime() {
		return self::alphaId(rand(1000, 9999) . time());
	}
	
	public static function setKey($key) {
		self::$_key = $key;
	}
	public static function getKey() {
		return self::$_key;
	}
	
	private function _alphaID($in, $to_num = false, $pad_up = false) {
		$index = $this->_index;
		$passKey = self::getKey();
		if($passKey !== null) {
			for($n = 0; $n < strlen($index); $n++) {
				$i[] = substr($index, $n, 1);
			}			
			$passhash = hash('sha256', $passKey);
			$passhash = (strlen($passhash) < strlen($index)) ? hash('sha512', $passKey) : $passhash;			
			for($n = 0; $n < strlen($index); $n++) {
				$p[] = substr($passhash, $n, 1);
			}
			array_multisort($p, SORT_DESC, $i);
			$index = implode($i);
		}
		
		$base = strlen($index);
		if($to_num) {
			$in = strrev($in);
			$out = 0;
			$len = strlen($in) - 1;
			for($t = 0; $t <= $len; $t++) {
				$bcpow = bcpow($base, $len - $t);
				$out = $out + strpos($index, substr($in, $t, 1)) * $bcpow;
			}
			if(is_numeric($pad_up)) {
				$pad_up--;
				if($pad_up > 0) $out -= pow($base, $pad_up);
			}
			$out = sprintf('%F', $out);
			$out = substr($out, 0, strpos($out, '.'));
		} else {
			if(is_numeric($pad_up)) {
				$pad_up--;
				if($pad_up > 0) $in += pow($base, $pad_up);
			}
			$out = "";
			for($t = floor(log($in, $base)); $t >= 0; $t--) {
				$bcp = bcpow($base, $t);
				$a = floor($in / $bcp) % $base;
				$out = $out . substr($index, $a, 1);
				$in = $in - ($a * $bcp);
			}
			$out = strrev($out);
		}
		return $out;
	}
}
